package com.framework.minio.utils;

import cn.hutool.core.io.IoUtil;
import com.framework.minio.config.MinIoConfig;
import io.minio.*;
import io.minio.messages.Bucket;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;

/**
 * @author lihanbo
 * @version 1.0
 * @date 2022/3/30 8:49
 */
@Component
@Slf4j
public class MinIoUtil {

    @Autowired
    private MinIoConfig minIoConfig;

    private static MinioClient minioClient;
    public static String bucketName;

    /**
     * 初始化minio配置
     *
     * @param :
     * @return: void
     * @date : 2020/8/16 20:56
     */
    @PostConstruct
    public void init() {
        try {
            if (minIoConfig.getEnable()) {
                bucketName = minIoConfig.getBucketName();
                minioClient = MinioClient.builder()
                        .endpoint(minIoConfig.getUrl())
                        .credentials(minIoConfig.getAccessKey(), minIoConfig.getSecretKey())
                        .build();
                createBucket(bucketName);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("初始化minio配置异常: 【{}】", e.fillInStackTrace());
        }
    }

    /**
     * 判断 bucket是否存在
     *
     * @param bucketName: 桶名
     * @return: boolean
     * @date : 2020/8/16 20:53
     */
    @SneakyThrows(Exception.class)
    public static boolean bucketExists(String bucketName) {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * 创建 bucket
     *
     * @param bucketName: 桶名
     * @return: void
     * @date : 2020/8/16 20:53
     */
    @SneakyThrows(Exception.class)
    public static void createBucket(String bucketName) {
        boolean isExist = bucketExists(bucketName);
        if (!isExist) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 获取全部bucket
     *
     * @param :
     * @return: java.util.List<io.minio.messages.Bucket>
     * @date : 2020/8/16 23:28
     */
    @SneakyThrows(Exception.class)
    public static List<Bucket> getAllBuckets() {
        return minioClient.listBuckets();
    }

    /**
     * 文件上传
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @param filePath:   文件路径
     * @date : 2020/8/16 20:53
     */
    @SneakyThrows(Exception.class)
    public static void upload(String bucketName, String fileName, String filePath) {
        minioClient.uploadObject(
                UploadObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .filename(filePath)
                        .build());
    }

    /**
     * 文件上传
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @param stream:     文件流
     * @date : 2020/8/16 23:40
     */
    @SneakyThrows(Exception.class)
    public static void upload(String bucketName, String fileName, InputStream stream) {
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .stream(stream, stream.available(), -1)
                        .build());
    }

    /**
     * 文件上传
     *
     * @param bucketName: 桶名
     * @date : 2020/8/16 23:40
     */
    @SneakyThrows(Exception.class)
    public static void upload(String bucketName, InputStream is, String fileName) {
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucketName)
                .object(fileName)
                .stream(is, is.available(), -1)
                .build());
    }

    /**
     * 删除文件
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @return: void
     * @date : 2020/8/16 20:53
     */
    @SneakyThrows(Exception.class)
    public static void deleteFile(String bucketName, String fileName) {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
    }

    /**
     * 下载文件
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @param response:
     * @return: void
     * @date : 2020/8/17 0:34
     */
    @SneakyThrows(Exception.class)
    public static void download(String bucketName, String fileName, HttpServletResponse response) {
        // 获取对象的元数据
        final ObjectStat stat = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(fileName).build());
        response.setContentType(stat.contentType());
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        InputStream is = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
        IoUtil.copy(is, response.getOutputStream());
        IoUtil.close(is);
    }

    /**
     * 下载文件
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @param savePath:   保存文件的本地路径
     * @return: void
     * @date : 2020/8/17 0:34
     */
    @SneakyThrows(Exception.class)
    public static void saveLocal(String bucketName, String fileName, String savePath) {
        // 获取对象的元数据
//        final ObjectStat stat = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(fileName).build());
        InputStream is = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
        FileOutputStream out = new FileOutputStream(savePath);
        IoUtil.copy(is, out);
        IoUtil.close(out);
        IoUtil.close(is);
    }

    /**
     * 获取minio文件的下载地址
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @return: java.lang.String
     * @date : 2020/8/16 22:07
     */
    @SneakyThrows(Exception.class)
    public static String getFileUrl(String bucketName, String fileName) {
        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).build());
    }
}
